/**
 *    @file       toolkit.cpp
 *
 *    @brief      
 *    @details
 *
 *    @version    1.0
 *    @date       12/11/2012 11:55:09 PM
 *
 *    @author     Theophilus, wangtf418@gmail.com
 */
#include <time.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <dirent.h>
#include "toolkit.h"

static const time_trans_base TIME_TRANS_BASE;

toolkit::toolkit()
{

}

toolkit::~toolkit()
{

}

//string toolkit==============================================
bf_size_t toolkit::sub_string(const bf_char_t *src_string, bf_size_t str_len, const std::string &sep)
{
	if(!src_string || str_len == 0 || sep.empty() || sep.length() > str_len)
	{
		return BF_SIZE_MAX;
	}
	bf_size_t pos = 0;
	bf_size_t sep_len = sep.length();
	bf_size_t endpos = str_len - sep_len;
	while (pos <= endpos)
	{
		bf_bool_t sameflag = true;
		for (bf_size_t i = 0; i < sep_len; i ++)
		{
			if (*(src_string + (i + pos)) != sep[i])
			{
				sameflag = false;
				break;
			}
		}
		if (sameflag == false)
		{
			pos ++;
		}
		else
		{
			return pos;
		}
	}
	return BF_SIZE_MAX;
}

bf_int_t toolkit::split_string_by_line(const bf_char_t *src_string, bf_size_t str_len, std::vector<bf_string_t> &str_arr_out)
{
	if(!src_string)
	{
		return BF_ERROR;
	}

	bf_size_t begin_offset = 0;
	bf_size_t end_offset = 0;
	for (bf_size_t i = 0; i < str_len; i ++)
	{
		if (*(src_string + i) == '\n')
		{
			if (begin_offset == end_offset)
			{
				begin_offset ++;
				end_offset ++;
			}
			else
			{
				if (*(src_string + (end_offset - 1)) == '\r')
				{
					str_arr_out.push_back(bf_string_t((bf_char_t*)src_string + begin_offset, end_offset - begin_offset - 1));
				}
				else
				{
					str_arr_out.push_back(bf_string_t((bf_char_t*)src_string + begin_offset, end_offset - begin_offset));
				}
				end_offset ++;
				begin_offset = end_offset;
			}
		}
		else
		{
			end_offset ++;
		}
	}
	if (begin_offset != end_offset)
	{
		str_arr_out.push_back(bf_string_t((bf_char_t*)src_string + begin_offset, end_offset - begin_offset));
	}
	return BF_OK;
}

bf_int_t toolkit::split_string_by_string(const bf_char_t *src_string, bf_size_t str_len, const std::string &sep, std::vector<bf_string_t> &str_arr_out, bf_bool_t emptystr /* = false */)
{
	if (!src_string)
	{
		return BF_ERROR;
	}
	str_arr_out.clear();
	if (sep.empty())
	{
		str_arr_out.push_back(bf_string_t((bf_char_t*)src_string, str_len));
		return BF_OK;
	}
	bf_size_t pos_last = 0;
	bf_size_t pos = 0;
	while (pos_last < str_len)
	{
		pos = toolkit::sub_string((bf_char_t*)(src_string + pos_last), str_len - pos_last, sep);
		if (pos == BF_SIZE_MAX)
		{
			str_arr_out.push_back(bf_string_t((bf_char_t*)(src_string + pos_last), str_len - pos_last));
			break;
		}
		else if (pos == 0)
		{
			if (emptystr)
			{
				str_arr_out.push_back(BF_EMPTY_STRING);
			}
			pos_last += sep.length();
		}
		else
		{
			str_arr_out.push_back(bf_string_t((bf_char_t*)(src_string + pos_last), pos));
			pos_last += pos + sep.length();
		}
	}
	return BF_OK;
}

bf_int_t toolkit::split_string_by_chars(const bf_char_t *src_string, bf_size_t str_len, const std::string &charset, std::vector<bf_string_t> &str_arr_out)
{
	if (!src_string)
	{
		return BF_ERROR;
	}
	str_arr_out.clear();
	if (charset.empty())
	{
		str_arr_out.push_back(bf_string_t((bf_char_t*)src_string, str_len));
		return BF_OK;
	}
	bf_size_t pos_last = 0;
	bf_size_t pos = 0;
	bf_size_t charnum = charset.length();
	while (pos < str_len)
	{
		bf_bool_t if_in_charset = false;
		for (bf_size_t i = 0; i < charnum; i ++)
		{
			if (*(src_string + pos) == charset[i])
			{
				if_in_charset = true;
				break;
			}
		}
		if (if_in_charset)
		{
			if (pos == pos_last)
			{
				pos ++;
				pos_last ++;
			}
			else
			{
				str_arr_out.push_back(bf_string_t((bf_char_t*)(src_string + pos_last), pos - pos_last));
				pos ++;
				pos_last = pos;
			}
		}
		else
		{
			pos ++;
		}
	}
	if (pos != pos_last)
	{
		str_arr_out.push_back(bf_string_t((bf_char_t*)(src_string + pos_last), pos - pos_last));  
	}
	return BF_OK;
}

void toolkit::trim_string(std::string &str, const std::string &char_list /*  = " \t\r\n" */)
{
	if (str.empty() || char_list.empty())
	{
		return;
	}
	bf_string_t str_tmp((bf_char_t*)str.c_str(), str.length());
	trim_string(str_tmp);
	if (str_tmp.m_len != str.length())
	{
		str = str_tmp.to_string();
	}
	return;
}

void toolkit::trim_string(bf_string_t &str, const std::string &char_list /*  = " \t\r\n" */)
{
	if (str.m_str == NULL || str.m_len == 0 || char_list.empty())
	{
		return;
	}
	bf_size_t str_len = str.m_len;
	bf_size_t char_num = char_list.length();

	bf_size_t begin_offset = 0;
	bf_bool_t if_tream = false;
	for (bf_size_t i = 0; i < str_len; i ++)
	{
		if_tream = false;
		for (bf_size_t j = 0; j < char_num; j ++)
		{
			if (str.m_str[i] == char_list[j])
			{
				if_tream = true;
				break;
			}
		}
		if (!if_tream)
		{
			break;
		}
		begin_offset ++;
	}

	if (begin_offset >= str_len)
	{
		str = BF_EMPTY_STRING;
		return;
	}
	
	bf_size_t end_offset = str_len - 1;
	for (bf_size_t i = str_len - 1; i >= begin_offset; i --)
	{
		if_tream = false;
		for (bf_size_t j = 0; j < char_num; j ++)
		{
			if (str.m_str[i] == char_list[j])
			{
				if_tream = true;
				break;
			}
		}
		if (!if_tream)
		{
			break;
		}
		end_offset --;
	}
	str = bf_string_t(str.m_str + begin_offset, end_offset - begin_offset + 1);
	return;
}

bf_int_t toolkit::get_string_by_label(const std::string &str, bf_size_t offset, const std::string &label_begin, const std::string &label_end, std::string &str_out, bf_size_t &pos_out, bf_bool_t ignores_case  /* = false */)
{
	if (offset >= str.length())
	{
		return BF_ERROR;
	}
	bf_char_t *real_str = (bf_char_t*)str.c_str() + offset;
	bf_char_t *begin = NULL;
	bf_char_t *end = NULL;
	if (label_begin == "")
	{
		begin = real_str;
	}
	else
	{
		if (ignores_case)
		{
			begin = strcasestr(real_str, label_begin.c_str());
		}
		else
		{
			begin = strstr(real_str, label_begin.c_str());
		}
		if (!begin)
		{
			return BF_ERROR;
		}
	}

	if (label_end == "")
	{
		str_out.append(begin + label_begin.length());
	}
	else
	{
		if (ignores_case)
		{
			end = strcasestr(real_str + label_begin.length(), label_end.c_str());
		}
		else
		{
			end = strstr(real_str + label_begin.length(), label_end.c_str());
		}
		if (!end)
		{
			return BF_ERROR;
		}
		str_out.append(begin + label_begin.length(), end - begin - label_begin.length());
	}
	pos_out = begin - real_str + label_begin.length();
	return BF_OK;
}

std::string toolkit::int2str(bf_int64_t num)
{
	bf_char_t buf[24];
	snprintf(buf, 24, "%lld", num);
	return std::string(buf);
}

bf_int64_t toolkit::str2int(const bf_char_t* str)
{
	return strtoll(str, NULL, 10);
}

bf_int_t toolkit::str2int(const bf_char_t *str, bf_int64_t &num_out)
{
	if (!str)
	{
		return BF_ERROR;
	}
	const bf_char_t *str_tmp = str;
	bf_int_t count = 0;
	while ((*str_tmp) != '\0')
	{
		count ++;
		if (count > BF_MAX_UINT64_DECIMALLEN)
		{
			return BF_ERROR;
		}
		if ((*str_tmp) == '-' && count == 1)
		{
			str_tmp ++;
			continue;
		}
		if ((*str_tmp) >= '0' && (*str_tmp) <= '9')
		{
			str_tmp ++;
			continue;
		}
		return BF_ERROR;
	}
	if (count == 0)
	{
		return BF_ERROR;
	}
	bf_int64_t num_tmp = strtoll(str, NULL, 10);
	if (num_tmp == LLONG_MIN || num_tmp == LLONG_MAX)
	{
		if (errno == ERANGE)
		{
			return BF_ERROR;
		}
	}
	num_out = num_tmp;
	return BF_OK;
}

bf_bool_t toolkit::is_ipstring(const std::string &str)
{
	if (str.length() < 7) //1.0.0.0
	{
		return false;
	}

	bf_int_t str_len = (bf_int_t)str.length();
	for (bf_int_t i = 0; i < str_len; i ++)
	{
		if (str[i] >= '0' && str[i] <= '9')
		{
			continue;
		}
		if (str[i] != '.')
		{
			return false;
		}
	}
	std::vector<bf_string_t> vec_out;
	split_string_by_string(str.c_str(), str.length(), ".", vec_out, true);
	if (vec_out.size() != 4)
	{
		return false;
	}
	for (bf_int_t i = 0; i < 4; i ++)
	{
		bf_int64_t num = str2int(vec_out[i].to_string().c_str());
		if (num < 0 || num > 255)
		{
			return false;
		}
	}
	return true;
}

std::string toolkit::inaddr2str(bf_uint_t inaddr)
{
	bf_char_t buf[16] = {0};
	inet_ntop(AF_INET, &inaddr, buf, 16);
	return std::string(buf);
}

bf_uint_t toolkit::str2inaddr(const std::string &str)
{
	bf_uint32_t inaddr;
	if (str2inaddr(str, inaddr) != BF_OK)
	{
		return INADDR_NONE;
	}
	return inaddr;
}

bf_int_t toolkit::str2inaddr(const std::string &str, bf_uint_t &inaddr_out)
{
	if (!is_ipstring(str))
	{
		return BF_ERROR;
	}
	if (inet_pton(AF_INET, str.c_str(), &inaddr_out) > 0)
	{
		return BF_OK;
	}
	return BF_ERROR;
}

bf_int_t toolkit::str_upper2lower(bf_char_t *str, bf_size_t strlen)
{
	if (!str)
	{
		return BF_ERROR;
	}
	for (bf_size_t i = 0; i < strlen; i ++)
	{
		if (str[i] >= 'A' && str[i] <= 'Z')
		{
			str[i] = str[i] + ('a' - 'A');
		}
	}
	return BF_OK;
}

bf_int_t toolkit::str_lower2upper(bf_char_t *str, bf_size_t strlen)
{
	if (!str)
	{
		return BF_ERROR;
	}
	for (bf_size_t i = 0; i < strlen; i ++)
	{
		if (str[i] >= 'a' && str[i] <= 'z')
		{
			str[i] = str[i] + ('A' - 'a');
		}
	}
	return BF_OK;
}

bf_uint64_t toolkit::hex2int(const bf_char_t *str, bf_size_t strlen)
{
	bf_uint64_t num;
	if (hex2int(str, strlen, num) != BF_OK)
	{
		return BF_UINT64_MAX;
	}
	return num;
}

bf_int_t toolkit::hex2int(const bf_char_t *str, bf_size_t strlen, bf_uint64_t &num_out)
{
	if (!str || strlen == 0 || strlen > BF_BASIC_WLEN64 * 2)
	{
		return BF_ERROR;
	}
	for (bf_size_t i = 0; i < strlen;i ++)
	{
		if (str[i] >= '0' && str[i] <= '9') 
		{
			continue;
		}
		if (str[i] >= 'a' && str[i] <= 'f')
		{
			continue;
		}
		if (str[i] >= 'A' && str[i] <= 'F')
		{
			continue;
		}
		return BF_ERROR;
	}
	bf_char_t buf[BF_BASIC_WLEN64 * 2 + 1] = {0};
	memcpy(buf, str, strlen);
	num_out = strtoull(buf, NULL, 16);
	return BF_OK;
}

std::string toolkit::int2hex(bf_uint64_t num, bf_basic_wordlen_t wordlen /* = BF_BASIC_WLEN0 */)
{
	bf_char_t buf[BF_BASIC_WLEN64 * 2 + 1] = {0};
	switch (wordlen)
	{
		case BF_BASIC_WLEN0:
			{
				snprintf(buf, sizeof(buf), "%llX", num);
				break;
			}
		case BF_BASIC_WLEN8:
			{
				snprintf(buf, sizeof(buf), "%02llX", num);
				break;
			}
		case BF_BASIC_WLEN16:
			{
				snprintf(buf, sizeof(buf), "%04llX", num);
				break;
			}
		case BF_BASIC_WLEN32:
			{
				snprintf(buf, sizeof(buf), "%08llX", num);
				break;
			}
		case BF_BASIC_WLEN64:
			{
				snprintf(buf, sizeof(buf), "%016llX", num);
				break;
			}
		default:
			{
				break;
			}
	}
	return std::string(buf);
}

bf_uint32_t toolkit::short_elf_hash(const bf_char_t *str, bf_size_t strlen)
{
	if (!str || strlen == 0)
	{
		return 0;
	}
	bf_ulong_t hash = 0;
	bf_ulong_t tmp = 0;
	for (bf_size_t i = 0; i < strlen; i ++)
	{
		hash = (hash << 4) + str[i];
		tmp = hash & 0xF0000000L;
		if (tmp)
		{
			hash ^= (tmp >> 24);
		}
		hash &= ~tmp;
	}
	return hash;
}

std::string toolkit::hex2bi(const bf_char_t *str, bf_size_t strlen)
{
	if (!str || strlen == 0 || (strlen % 2) != 0)
	{
		return "";
	}
	
	bf_size_t bilen = strlen / 2;
	std::string str_ret;
	str_ret.reserve(bilen);

	bf_char_t buf[3] = {0};
	bf_char_t ch = 0;
	for (bf_size_t i = 0; i < bilen; i ++)
	{
		strncpy(buf, str + i * 2, 2);
		ch = (bf_char_t)strtoul(buf, 0, 16);
		str_ret.append(1, ch);
	}
	return str_ret;
}

std::string toolkit::bi2hex(const bf_char_t *str, bf_size_t strlen)
{
	if (!str || strlen == 0)
	{
		return "";
	}
	std::string str_ret;
	str_ret.reserve(strlen * 2);

	bf_char_t buf[3] = {0};
	for (bf_size_t i = 0; i < strlen; i ++)
	{
		snprintf(buf, sizeof(buf), "%02X", (bf_uchar_t)str[i]);
		str_ret.append(buf, 2);
	}
	return str_ret;
}

//time toolkit========================================
bf_time_t toolkit::get_unixtime()
{
	return time(NULL);
}

bf_int_t toolkit::get_unixtime(bf_time_t &sec, bf_time_t &usec)
{
	struct timeval tv;
	gettimeofday(&tv, NULL);
	sec = tv.tv_sec;
	usec = tv.tv_usec;
	return BF_OK;
}

void toolkit::get_monotonic_time(bf_time_t &sec, bf_long_t &nsec)
{
	struct timespec time;
	clock_gettime(CLOCK_MONOTONIC, &time);
	sec = time.tv_sec;
	nsec = time.tv_nsec;
}

void toolkit::sec2time(bf_time_t unixtime, bf_tm_t &time_out)
{
	struct tm time;
	localtime_r(&unixtime, &time);	
	time_out.m_year = time.tm_year + 1900;
	time_out.m_month = time.tm_mon + 1;
	time_out.m_day = time.tm_mday;
	time_out.m_hour = time.tm_hour;
	time_out.m_min = time.tm_min;
	time_out.m_sec = time.tm_sec;
}

std::string toolkit::sec2time(bf_time_t unixtime)
{
	bf_char_t buf[24];
	bf_int_t year, month, day, hour, min, sec;
	struct tm tm_tmp;
	localtime_r(&unixtime, &tm_tmp);

	year = tm_tmp.tm_year + 1900;
	month = tm_tmp.tm_mon + 1;
	day = tm_tmp.tm_mday;
	hour = tm_tmp.tm_hour;
	min = tm_tmp.tm_min;
	sec = tm_tmp.tm_sec;
	snprintf(buf, sizeof(buf), "%04d%02d%02d%02d%02d%02d", year, month, day, hour, min, sec);
	return std::string(buf);
}

std::string toolkit::sec2formattime(bf_time_t unixtime)
{
	bf_char_t buf[24];
	bf_int_t year, month, day, hour, min, sec;
	struct tm tm_tmp;
	localtime_r(&unixtime, &tm_tmp);

	year = tm_tmp.tm_year + 1900;
	month = tm_tmp.tm_mon + 1;
	day = tm_tmp.tm_mday;
	hour = tm_tmp.tm_hour;
	min = tm_tmp.tm_min;
	sec = tm_tmp.tm_sec;
	snprintf(buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, min, sec);
	return std::string(buf);
}

std::string toolkit::sec2httptime(bf_time_t unixtime, std::string tz_type /* = "GMT" */)
{
	bf_char_t buf[32];
	bf_int_t year, month, day, wday, hour, min, sec;
	if (tz_type == "GMT")
	{
		unixtime += TIME_TRANS_BASE.get_timezone();
	}
	struct tm tm_tmp;
	localtime_r(&unixtime, &tm_tmp);

	year = tm_tmp.tm_year + 1900;
	month = tm_tmp.tm_mon;
	day = tm_tmp.tm_mday;
	wday = tm_tmp.tm_wday;
	hour = tm_tmp.tm_hour;
	min = tm_tmp.tm_min;
	sec = tm_tmp.tm_sec;
	snprintf(buf, sizeof(buf), "%s, %02d %s %04d %02d:%02d:%02d %s",
			BF_WEEK_STRING[wday], day, BF_MONTH_STRING[month], year, hour, min, sec, tz_type.c_str());
	return std::string(buf);
}

bf_time_t toolkit::time2sec(const struct bf_tm_t &time)
{
	struct tm tm_tmp;
	tm_tmp.tm_year = time.m_year - 1900;
	tm_tmp.tm_mon = time.m_month - 1;
	tm_tmp.tm_mday = time.m_day;
	tm_tmp.tm_hour = time.m_hour;
	tm_tmp.tm_min = time.m_min;
	tm_tmp.tm_sec = time.m_sec;
	return mktime(&tm_tmp);
}

///YYYYMMDDHHMMSS
bf_time_t toolkit::time2sec(const std::string &time)
{
	if (time.length() != 14)
	{
		return INVALID_TIME;
	}
	struct tm tm_tmp;
	bf_int64_t num;
	if (str2int(time.substr(0, 4).c_str(), num) != BF_OK || num < 0) return INVALID_TIME;
	tm_tmp.tm_year = num - 1900;

	if (str2int(time.substr(4, 2).c_str(), num) != BF_OK || num < 0) return INVALID_TIME;
	tm_tmp.tm_mon = num - 1;

	if (str2int(time.substr(6, 2).c_str(), num) != BF_OK || num < 0) return INVALID_TIME;
	tm_tmp.tm_mday = num;
	
	if (str2int(time.substr(8, 2).c_str(), num) != BF_OK || num < 0) return INVALID_TIME;
	tm_tmp.tm_hour = num;

	if (str2int(time.substr(10, 2).c_str(), num) != BF_OK || num < 0) return INVALID_TIME;
	tm_tmp.tm_min = num;

	if (str2int(time.substr(12, 2).c_str(), num) != BF_OK || num < 0) return INVALID_TIME;
	tm_tmp.tm_sec = num;

	bf_time_t time_ret = mktime(&tm_tmp);	
	return (time_ret != -1)? time_ret:INVALID_TIME;
}

///YYYY-MM-DD HH:MM:SS
bf_time_t toolkit::formattime2sec(const std::string &time)
{
	std::vector<bf_string_t> str_arr;
	bf_int_t ret = split_string_by_chars(time.c_str(), time.length(), " ", str_arr);
	if (ret != BF_OK || str_arr.size() != 2) return INVALID_TIME;


	std::string datastr = str_arr[0].to_string();
	std::string timestr = str_arr[1].to_string();
	if (datastr.length() != 10 || timestr.length() != 8) return INVALID_TIME;

	struct tm tm_tmp;
	bf_int64_t num;
	if (str2int(datastr.substr(0, 4).c_str(), num) != BF_OK || num < 0) return INVALID_TIME;
	tm_tmp.tm_year = num - 1900;

	if (str2int(datastr.substr(5, 2).c_str(), num) != BF_OK || num < 0) return INVALID_TIME;
	tm_tmp.tm_mon = num - 1;

	if (str2int(datastr.substr(8, 2).c_str(), num) != BF_OK || num < 0) return INVALID_TIME;
	tm_tmp.tm_mday = num;

	if (str2int(timestr.substr(0, 2).c_str(), num) != BF_OK || num < 0) return INVALID_TIME;
	tm_tmp.tm_hour = num;

	if (str2int(timestr.substr(3, 2).c_str(), num) != BF_OK || num < 0) return INVALID_TIME;
	tm_tmp.tm_min = num;

	if (str2int(timestr.substr(6, 2).c_str(), num) != BF_OK || num < 0) return INVALID_TIME;
	tm_tmp.tm_sec = num;

	bf_time_t time_ret = mktime(&tm_tmp);	
	return (time_ret != -1)? time_ret:INVALID_TIME;
}

///Wed, 12 Feb 2014 10:57:48 GMT
bf_time_t toolkit::httptime2sec(const std::string &time)
{
	std::vector<bf_string_t> str_arr;
	bf_int_t ret = split_string_by_chars(time.c_str(), time.length(), ", ", str_arr);
	if (ret != BF_OK || str_arr.size() != 6) return INVALID_TIME;

	std::string wdatastr = str_arr[0].to_string();
	std::string daystr = str_arr[1].to_string();
	std::string monstr = str_arr[2].to_string();
	std::string yearstr = str_arr[3].to_string();
	std::string timestr = str_arr[4].to_string();

	if (daystr.length() != 2 || monstr.length() != 3 || yearstr.length() != 4 || timestr.length() != 8) return INVALID_TIME;

	struct tm tm_tmp;
	bf_int64_t num;
	if ((num = TIME_TRANS_BASE.findweek(wdatastr)) < 0) return INVALID_TIME;
	tm_tmp.tm_wday = num;

	if ((num = TIME_TRANS_BASE.findmonth(monstr)) < 0) return INVALID_TIME;
	tm_tmp.tm_mon = num;
	
	if (str2int(yearstr.c_str(), num) != BF_OK || num < 0) return INVALID_TIME;
	tm_tmp.tm_year = num - 1900;

	if (str2int(daystr.c_str(), num) != BF_OK || num < 0) return INVALID_TIME;
	tm_tmp.tm_mday = num;

	if (str2int(timestr.substr(0, 2).c_str(), num) != BF_OK || num < 0) return INVALID_TIME;
	tm_tmp.tm_hour = num;

	if (str2int(timestr.substr(3, 2).c_str(), num) != BF_OK || num < 0) return INVALID_TIME;
	tm_tmp.tm_min = num;

	if (str2int(timestr.substr(6, 2).c_str(), num) != BF_OK || num < 0) return INVALID_TIME;
	tm_tmp.tm_sec = num;

	bf_time_t time_ret = mktime(&tm_tmp);	
	if (time_ret == -1) return INVALID_TIME;
	if (str_arr[5].to_string() == "GMT") time_ret -= TIME_TRANS_BASE.get_timezone();

	return time_ret;
}

void toolkit::usleep_byselect(bf_time_t sec, bf_time_t usec)
{
	if (usec >= 1000000)
	{
		sec += usec / 1000000;
		usec = usec % 1000000;
	}
	struct timeval timeout;
	timeout.tv_sec = sec;
	timeout.tv_usec = usec;
	select(0, NULL, NULL, NULL, &timeout);
}

//file toolkit
std::string toolkit::get_workdir()
{
	std::string workdir = "";
	bf_char_t *buf = new bf_char_t[BF_PATH_MAX];
	if (getcwd(buf, BF_PATH_MAX) != NULL)
	{
		workdir = buf;
	}
	delete [] buf;
	return workdir;
}

bf_int_t toolkit::get_filelist(const std::string &dir, std::vector<std::string> &filelist, std::string suffix /* = "" */)
{
	DIR *dir_open = opendir(dir.c_str());
	if (!dir_open)
	{
		return BF_ERROR;
	}

	bf_char_t *filename = new bf_char_t[BF_PATH_MAX];
	memset(filename, 0, BF_PATH_MAX);
	struct dirent *dirstream;
	while ((dirstream = readdir(dir_open)) != NULL)
	{
		if (suffix != "")
		{
			size_t len = strlen(dirstream->d_name);
			if (len < suffix.length())
			{
				continue;
			}
			if (memcmp(dirstream->d_name + (len - suffix.length()), suffix.c_str(), suffix.length()))
			{
				continue;
			}
		}

		if ((*dir.rbegin()) == '/')
		{
			snprintf(filename, BF_PATH_MAX, "%s%s", dir.c_str(), dirstream->d_name);
		}
		else
		{
			snprintf(filename, BF_PATH_MAX, "%s/%s", dir.c_str(), dirstream->d_name);
		}
		filelist.push_back(filename);
	}
	closedir(dir_open);
	return 0;
}

//net toolkit
bf_int_t toolkit::parsedomain(const std::string &domain, std::vector<bf_uint32_t> &iplist)
{
	struct hostent *hp = gethostbyname(domain.c_str());
	if (hp == NULL) 
	{
		return BF_ERROR;
	}
	iplist.clear();
	in_addr ia_tmp;
	bf_char_t **pp = hp->h_addr_list;
	while(*pp)
	{
		memcpy(&ia_tmp.s_addr,  pp[0], hp->h_length);
		iplist.push_back((bf_uint32_t)ia_tmp.s_addr);
		pp ++;
	}
	return BF_OK;
}

//math toolkit
void toolkit::srand()
{
	static bf_int_t flag = 0;
	if (flag == 0)
	{
		::srand(time(NULL));
		flag = 1;
	}
}


